
                /*********************************************
                **                                          **
                **                                          **
                **                newCommR                  **
                **                                          **
                **                                          **
                *********************************************/
                /*********************************************
                **                                          **
                **         Author Jean-Marc Adamo           **
                **                12/31/97                  **
                **       Copyright (C) 1997-2008 JMA        **
                *********************************************/



/*
** execute with 7 processes
                ^^^^^^^^^^^
*/

#include "arch.h"
#include "A.utilities"

//user program

Coll_id cid1, cid2, cid3, cid4, cid5;

//on most homogenous systems, explicit setting 
//wont be necessary (try commenting the
//setting lines, you should get the same values
//for all cid).
void init(int, char **){
   cid1.set();
   cid2.set();
   cid3.set();
   cid4.set();
   cid5.set();
   fprintf(Sdf::trace, "node%d: cid1=%d, cid2=%d, cid3=%d, cid4=%d, cid5=%d\n",
           Sdf::PROC_ID, cid1.get(), cid2.get(), cid3.get(), cid4.get(), cid5.get());
   fflush(Sdf::trace);
}

class Root_proc: public Thread{

   public:

        Root_proc()
                : Thread((Tmf0_ptr)&Root_proc::body){}

        void body(){

            fprintf(Sdf::trace, "node %d, in Root_proc::starts\n", Sdf::PROC_ID);
            fflush(Sdf::trace);

            int ranks1[3] = {2, 4, 5};
            Group *incl_grp1 = Sdf::incl(Sdf::COMML_WORLD, 3, ranks1);
            int incl_grp1_size = incl_grp1->size();
            int incl_grp1_rank = incl_grp1->rank();

            int ranks2[4] = {1, 3, 4, 5};
            Group *incl_grp2 = Sdf::incl(Sdf::COMML_WORLD, 4, ranks2);
            int incl_grp2_size = incl_grp2->size();
            int incl_grp2_rank = incl_grp2->rank();

            int ranks3[6] = {1, 2, 3, 4, 5, 6};
            Group *super_grp = Sdf::incl(Sdf::COMML_WORLD, 6, ranks3);
            int super_grp_size = super_grp->size();
            int super_grp_rank = super_grp->rank();

            fprintf(Sdf::trace, "node %d, size1 =%d, size2 =%d, size3 =%d, rank1 =%d, rank2 =%d, rank3 =%d\n", 
                    Sdf::PROC_ID, 
                    incl_grp1_size, incl_grp2_size, super_grp_size,
                    incl_grp1_rank, incl_grp2_rank, super_grp_rank);
            fflush(Sdf::trace);

            CommL *comm1 = incl_grp1->commit(cid1, Sdf::COMML_WORLD);

            CommL *comm2 = incl_grp2->commit(cid2, Sdf::COMML_WORLD);

            CommL *super_comm = super_grp->commit(cid3, Sdf::COMML_WORLD);

            fprintf(Sdf::trace, "node %d, comm1=%d, comm2=%d, super_comm=%d, size1=%d, size2=%d, size3=%d\n", 
                    Sdf::PROC_ID, comm1, comm2, super_comm,
                    comm1->size(), comm2->size(), super_comm->size());
            fflush(Sdf::trace);

            int cw_rank = Sdf::COMML_WORLD->rank();

            if(cw_rank > 0){
               CommR *commr = Sdf::newCommR(cid4, comm1, comm2, super_comm);
               if(cw_rank < 6){
                  int *rem_ranks;
                  int *loc_ranks;

                  rem_ranks = commr->get_remote_CommL()->get_world_ranks();
                  loc_ranks = commr->get_local_CommL()->get_world_ranks();

                  int i;
                  int size = commr->get_local_CommL()->size();
                  fprintf(Sdf::trace, "node %d, >>>local  CommL, size=%d\n", 
                          Sdf::PROC_ID, size);
                  for(i=0; i<size; i++)
                  fprintf(Sdf::trace, "node %d,                        loc_ranks[%d]=%d\n", 
                          Sdf::PROC_ID, i, loc_ranks[i]);
                  size = commr->get_remote_CommL()->size();
                  fprintf(Sdf::trace, "node %d, >>>remote CommL, size=%d\n", 
                          Sdf::PROC_ID, size);
                  for(i=0; i<size; i++)
                     fprintf(Sdf::trace, "node %d,                        rem_ranks[%d]=%d\n", 
                             Sdf::PROC_ID, i, rem_ranks[i]);
                  fflush(Sdf::trace);

                  delete []rem_ranks;
                  delete []loc_ranks;

                  CommL *merge_comm = commr->merge(cid5, Sdf::N);
                                   //to merge in the order comm1, comm2
                                   //switch to Sdf::C for merging in the order comm2, comm1
                  int *ranks = merge_comm->get_world_ranks();
                  size = merge_comm->size();
                  fprintf(Sdf::trace, "node %d, >>>merge_comm, size=%d\n", 
                          Sdf::PROC_ID, size);
                  for(i=0; i<size; i++)
                     fprintf(Sdf::trace, "node %d,                            ranks[%d]=%d\n", 
                             Sdf::PROC_ID, i, ranks[i]);
                  fflush(Sdf::trace);
                  delete merge_comm;
                  delete []ranks;
               }

               delete comm1;
               delete comm2;
               delete super_comm;
               delete commr;

            }

            fprintf(Sdf::trace, "node %d, in Root_proc::finishes\n", Sdf::PROC_ID);
            fflush(Sdf::trace);
        }
};
//end of user program

MAIN(Root_proc, init, Sdf::empty, Sdf::empty)
